/*
 * handsfree.cpp - handsfree HFPD-service interface
 *
 * Copyright (C) 2010-2011 Serge Begger
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "handsfree.h"
#include "ui_handsfree.h"
#include "QDebug"

handsfree::handsfree(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::handsfree)
{
    ui->setupUi(this);
    ui->endCallButton->setEnabled(false);
    createCallMessage();
    numPhonePanel = new numPanel(this,false,ui->frameNumPad->geometry());
    connect(numPhonePanel, SIGNAL(putFreq()), this, SLOT(updateNumber()));

    messages = new myMessage(0);

    lastNumber = "";
    error =false;
    incCall = false;
    service = 0;roam = 0; signal = 0; battchg = 0; voiceMail = 0;
    lastError = QString("");
    currState = false;
    devList = new QList<QString>;

    settings = new QSettings("carpc", "handsfree", this);
    settings->setPath(QSettings::IniFormat,QSettings::UserScope,"carpc");

    PhoneBook = new phonebook(this);
    connect(PhoneBook, SIGNAL(hideWidget()), this, SLOT(phoneBookHidden()));
    connect(PhoneBook, SIGNAL(selectNumber()),this,SLOT(selectNumberPhBook()));

    handsFree = new QDBusInterface("net.sf.nohands.hfpd","/net/sf/nohands/hfpd",
            "net.sf.nohands.hfpd.HandsFree",QDBusConnection::sessionBus(),this);

    handsFree->call("Start");
    if ( handsFree->lastError().name() != "")
    {
        lastError = handsFree->lastError().message();
        //messages->exec(0,lastError.toUtf8());
        error = true;
    }

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd","/net/sf/nohands/hfpd",
                                          "net.sf.nohands.hfpd.HandsFree","SystemStateChanged",
                                          this,SLOT(systemState(bool)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd","/net/sf/nohands/hfpd",
                                          "net.sf.nohands.hfpd.HandsFree","InquiryStateChanged",
                                          this,SLOT(inquiryState(bool)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd","/net/sf/nohands/hfpd",
                                          "net.sf.nohands.hfpd.HandsFree","InquiryResult",
                                          this,SLOT(findDev(QString, unsigned int)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd","/net/sf/nohands/hfpd",
                                          "net.sf.nohands.hfpd.HandsFree","AudioGatewayAdded",
                                          this,SLOT(agAdded(QDBusObjectPath)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd","/net/sf/nohands/hfpd",
                                          "net.sf.nohands.hfpd.HandsFree","LogMessage",
                                          this,SLOT(prnMessage(unsigned int, QString)));

    handsFree->setProperty("AutoRestart",true);

    agInterface = new audioGateway(this);
    connect(agInterface, SIGNAL(agOpen(bool)),this,SLOT(openAudioGW(bool)));
    connect(agInterface, SIGNAL(agCallSt(unsigned char)),this,SLOT(callChange(unsigned char)));
    connect(agInterface, SIGNAL(inCall(QString)),this,SLOT(inCall(QString)));
    connect(agInterface, SIGNAL(indicatorChange(QString,int)),this,SLOT(indChange(QString,int)));

    sndInterface = new soundIO(this);
}

handsfree::~handsfree()
{
    if (devList->count() > 0){
        for (int i= 0; i < devList->count(); ++i){
            handsFree->call("RemoveDevice", devList->at(i));
        }
    }
    handsFree->call("Stop");
    delete ui;
}

void handsfree::createCallMessage()
{
    callMessage = new QMessageBox(this);
    cancelButton = new QPushButton(this);
    QIcon icon0;
    icon0.addFile(QString::fromUtf8(":/buttons/res/call-stop.png"), QSize(), QIcon::Normal, QIcon::Off);
    cancelButton->setIcon(icon0);
    cancelButton->setIconSize(QSize(80, 80));
    callMessage->addButton(cancelButton,QMessageBox::AcceptRole);

    defButton = new QPushButton(this);
    QIcon icon1;
    icon1.addFile(QString::fromUtf8(":/buttons/res/call-start.png"), QSize(), QIcon::Normal, QIcon::Off);
    defButton->setIcon(icon1);
    defButton->setIconSize(QSize(80, 80));
    callMessage->addButton(defButton,QMessageBox::RejectRole);

    QFont font;
    font.setPointSize(20);
    font.setBold(true);
    font.setWeight(75);
    callMessage->setFont(font);
    connect(callMessage, SIGNAL(rejected()), this, SLOT(hangUp()));
    connect(callMessage, SIGNAL(accepted()), this, SLOT(answer()));
}

void handsfree::selectNumberPhBook()
{
    ui->phoneNumLabel->setText(PhoneBook->currNumber);
    ui->nameLabel->setText(PhoneBook->currName);
    on_stCallButton_pressed();
}

void handsfree::on_backButton_pressed()
{
    ui->phoneNumLabel->setText("");
    ui->nameLabel->setText("");
    emit hideWidget();
}

void handsfree::on_deleteButton_pressed()
{
    ui->phoneNumLabel->setText(ui->phoneNumLabel->text().remove(ui->phoneNumLabel->text().count()-1,1));
    numPhonePanel->freq->remove(numPhonePanel->freq->count()-1,1);
    if (!ui->nameLabel->text().isEmpty())
        ui->nameLabel->setText("");
}

void handsfree::on_stCallButton_pressed()
{
    if(ui->phoneNumLabel->text().size() == 0)
        ui->phoneNumLabel->setText(lastNumber);
    dial();
}

void handsfree::on_endCallButton_pressed()
{
    hangUp();
}

void handsfree::on_muteButton_toggled(bool flag)
{
    sndInterface->mute(flag);
}

void handsfree::on_voiceCallButton_pressed()
{
    agInterface->voiceRecognition(true);
}

void handsfree::on_phoneBookButton_pressed()
{
    ui->centralWidget->hide();
    numPhonePanel->hide();
    PhoneBook->show();
}

void handsfree::phoneBookHidden()
{
    ui->centralWidget->show();
    numPhonePanel->show();
}

void handsfree::updateNumber()
{
    ui->phoneNumLabel->setText(numPhonePanel->freq->toLatin1());
}

void handsfree::startHFS()
{
    //Load HandsFree settings
    QString devAddr = settings->value("devAddr").toString();
    bool connDev = settings->value("devConn").toBool();
    if (!devAddr.isEmpty() && connDev) {
        QString devDBusAddr = conDevice(devAddr);
        if ( handsFree->lastError().name() != ""){
            lastError = handsFree->lastError().message();
            //messages->exec(0,lastError.toUtf8());
            return;
        }
        agInterface->createAg(devDBusAddr);
        agInterface->connectAg();
        if (agInterface->error){
            //messages->exec(0,agInterface->agIfase->lastError().message().toUtf8());
            return;
        }
        PhoneBook->btaddr = devAddr;
    }
}

void handsfree::stopHFS() {
    if (agInterface)
       agInterface->disconnAg();
}

void handsfree::openAudioGW(bool flag)
{
    if (flag) {
        sndInterface->agStart(currPath);
        if (sndInterface->error){
           //messages->exec(0,sndInterface->soundPump->lastError().message().toUtf8());
           return;
        }
    } else {
        agInterface->disconnAg();
    }
   currState = true;
   emit openAGW(flag);
}

void handsfree::indChange(QString indicator, int value)
{
    if (indicator == "service")
        service = value;
    else if (indicator == "roam")
        roam = value;
    else if (indicator == "signal")
        signal = value;
    else if (indicator == "battchg")
        battchg = value;
    else if (indicator == "Voice Mail")
        voiceMail = value;

    updateUi();
}

void handsfree::callChange(unsigned char state)
{
//    исходящий - 2
//    сняли трубу - 3
//    положили трубу - 1
//    входящий звонок - 4
//    ответил - 5
//    сняли трубу - 3
    if (state == 1) {
        ui->stCallButton->setEnabled(true);
        ui->endCallButton->setEnabled(false);
        if(callMessage->isVisible())
            callMessage->reject();
        emit muteSound(false);
    } else if (state == 2 || state == 3) {
        ui->stCallButton->setEnabled(false);
        ui->endCallButton->setEnabled(true);
        if (state == 3)
            emit muteSound(true);
    } else if(state == 4) {
        emit muteSound(true);
    }

}

void handsfree::inCall(QString number)
{
    if (!incCall) {
        if(!number.isEmpty()) {
            incCall = true;
            callMessage->setText("Incoming CALL - "+number+"%/n"+"Name: ");
            callMessage->exec();
        }
    }
}

void handsfree::updateUi()
{
    switch (battchg) {
    case 1:
        ui->labelBatt->setPixmap(QPixmap(QString::fromUtf8(":/batt/res/gpm-battery-000.png")));
        break;
    case 2:
        ui->labelBatt->setPixmap(QPixmap(QString::fromUtf8(":/batt/res/gpm-battery-020.png")));
        break;
    case 3:
        ui->labelBatt->setPixmap(QPixmap(QString::fromUtf8(":/batt/res/gpm-battery-040.png")));
        break;
    case 4:
        ui->labelBatt->setPixmap(QPixmap(QString::fromUtf8(":/batt/res/gpm-battery-080.png")));
        break;
    case 5:
        ui->labelBatt->setPixmap(QPixmap(QString::fromUtf8(":/batt/res/gpm-battery-100.png")));
        break;
    }
    switch (signal) {
    case 1:
        ui->labelSignal->setPixmap(QPixmap(QString::fromUtf8(":/sig/res/signal-01.svg")));
        break;
    case 2:
        ui->labelSignal->setPixmap(QPixmap(QString::fromUtf8(":/sig/res/signal-03.svg")));
        break;
    case 3:
        ui->labelSignal->setPixmap(QPixmap(QString::fromUtf8(":/sig/res/signal-06.svg")));
        break;
    case 4:
        ui->labelSignal->setPixmap(QPixmap(QString::fromUtf8(":/sig/res/signal-08.svg")));
        break;
    case 5:
        ui->labelSignal->setPixmap(QPixmap(QString::fromUtf8(":/sig/res/signal-10.svg")));
        break;
    }
    ui->labelOperator->setText(agInterface->queryOperator());
}

void handsfree::dial()
{
    QString number = ui->phoneNumLabel->text();
    if(!number.isEmpty())
    {
        lastNumber = number;
        agInterface->dial(number);
        if (agInterface->error)
        {
            error = true;
            lastError = agInterface->agIfase->lastError().message();
            messages->exec(0,lastError.toUtf8());
            return;
        }
    }
}

void handsfree::hangUp()
{
    if (agInterface->agCurrCallState == 1)
        return;

    agInterface->hangUp();
    if (agInterface->error)
    {
        error = true;
        lastError = agInterface->agIfase->lastError().message();
        messages->exec(0,lastError.toUtf8());
        return;
     }
    incCall = false;
}

void handsfree::answer()
{
    agInterface->answer();
    if (agInterface->error)
    {
        error = true;
        lastError = agInterface->agIfase->lastError().message();
        messages->exec(0,lastError.toUtf8());
        return;
    }
    incCall = false;
}

void handsfree::startScan()
{
    if (error)
        return;
    devList->clear();
    handsFree->call("StartInquiry");
    if ( handsFree->lastError().name() != "")
    {
        lastError = handsFree->lastError().message();
        messages->exec(0,lastError.toUtf8());
        error = true;
        return;
    }
}

QString handsfree::getDevName(QString addr)
{
    if (error)
        return "";
    QDBusMessage name = handsFree->call("GetName",addr);
    if ( handsFree->lastError().name() != "")
    {
        error = true;
        lastError = handsFree->lastError().message();
        messages->exec(0,lastError.toUtf8());
        return addr;
    }
    return name.arguments()[0].toString();
}

QString handsfree::conDevice(QString addr)
{
    if (error)
        return "";
    QDBusReply<QDBusObjectPath> path = handsFree->call("AddDevice",addr,false);
    if ( handsFree->lastError().name() != "")
    {
        error = true;
        lastError = handsFree->lastError().message();
        messages->exec(0,lastError.toUtf8());
        return "";
    }
    return path.value().path();
}

void handsfree::findDev(QString addr, unsigned int classDev)
{
    (void)classDev;
    devList->append(addr);
}

void handsfree::systemState(bool sysState)
{
    (void)sysState;
}

void handsfree::inquiryState(bool state)
{
    currState = state;
    emit changeState();
}

void handsfree::agAdded(QDBusObjectPath path)
{
    currPath = path;
}

void handsfree::prnMessage(int level, QString message)
{
    (void)level;
    messages->exec(0,message.toLocal8Bit());
}

audioGateway::audioGateway(QObject *parent) :
    QObject(parent)
{
    error =false;
    agCurrCallState = 0;
}

void audioGateway::createAg(QString path)
{
    agIfase = new QDBusInterface("net.sf.nohands.hfpd",path,
            "net.sf.nohands.hfpd.AudioGateway",QDBusConnection::sessionBus(),this);

    agIfase->setProperty("AutoReconnect",true);

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd",path,
                                          "net.sf.nohands.hfpd.AudioGateway","StateChanged",
                                          this,SLOT(agState(unsigned char)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd",path,
                                          "net.sf.nohands.hfpd.AudioGateway","AudioStateChanged",
                                          this,SLOT(agAudioState(unsigned char)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd",path,
                                          "net.sf.nohands.hfpd.AudioGateway","CallStateChanged",
                                          this,SLOT(agCallState(unsigned char)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd",path,
                                          "net.sf.nohands.hfpd.AudioGateway","IndicatorChanged",
                                          this,SLOT(indChange(QString,int)));

    QDBusConnection::sessionBus().connect("net.sf.nohands.hfpd",path,
                                          "net.sf.nohands.hfpd.AudioGateway","Ring",
                                          this,SLOT(ring(QString,int,QString,int,QString)));

}

audioGateway::~audioGateway()
{
    //agIfase->call("Disconnect");
}

void audioGateway::connectAg()
{
    error =false;
    agIfase->call("Connect");
    if ( agIfase->lastError().name() != ""){
        error = true;
    }
}

void audioGateway::disconnAg()
{
    error =false;
    agIfase->call("Disconnect");
    if ( agIfase->lastError().name() != ""){
        error = true;
    }
}

void audioGateway::agAudioOpen()
{
    error =false;
    agIfase->call("OpenAudio");
    if ( agIfase->lastError().name() != ""){
        error = true;
    }
}

void audioGateway::voiceRecognition(bool flag)
{
    error =false;
    agIfase->call("SetVoiceRecognition",flag);
    if ( agIfase->lastError().name() != ""){
        error = true;
    }
}

QString audioGateway::queryOperator()
{
    error =false;
    QDBusMessage params = agIfase->call("QueryOperator");
    if ( agIfase->lastError().name() != ""){
        error = true;
        return "";
    }
    return params.arguments()[2].toString();
}

void audioGateway::agState(unsigned char state)
{
    if (state == 4)
        emit agOpen(true);
    else if (state == 2)
        emit agOpen(false);
}

void audioGateway::agAudioState(unsigned char state) {
    qDebug() << state;
}

void audioGateway::agCallState(unsigned char state)
{
    agCurrCallState = state;
    emit agCallSt(state);
}

void audioGateway::indChange(QString indicator, int value)
{
    emit indicatorChange(indicator, value);
}

void audioGateway::ring(QString num,int numType,QString subaddr,int subaddrType,QString name)
{
    (void)numType;
    (void)subaddr;
    (void)subaddrType;
    (void)name;
    emit inCall(num);
}

void audioGateway::dial(QString number)
{
    agIfase->call("Dial",number);
    if ( agIfase->lastError().name() != ""){
        error = true;
        return;
    }
}

void audioGateway::hangUp()
{
    agIfase->call("HangUp");
    if ( agIfase->lastError().name() != ""){
        error = true;
        return;
    }
}

void audioGateway::answer()
{
    agIfase->call("Answer");
    if ( agIfase->lastError().name() != ""){
        error = true;
        return;
    }
}

soundIO::soundIO(QObject *parent) :
    QObject(parent)
{
    error =false;
    soundPump = new QDBusInterface("net.sf.nohands.hfpd","/net/sf/nohands/hfpd/soundio",
            "net.sf.nohands.hfpd.SoundIo",QDBusConnection::sessionBus(),this);

    soundPump->call("SetDriver","ALSA","access=thread");
    if ( soundPump->lastError().name() != ""){
        error = true;
    }

}

void soundIO::agStart(QDBusObjectPath agpath)
{
    error =false;
    soundPump->call("AudioGatewayStart", qVariantFromValue(agpath),true);
    if ( soundPump->lastError().name() != ""){
        error = true;
    }
}

void soundIO::mute(bool flag)
{
    error =false;
    soundPump->setProperty("Mute",flag);
    if ( soundPump->lastError().name() != ""){
        error = true;
    }
}

soundIO::~soundIO()
{
}
